package cn.com.rexen.rplus.sa.controller;

import cn.com.rexen.rplus.controller.CURDControllerSupport;
import cn.com.rexen.rplus.core.criteria.Criteria;
import cn.com.rexen.rplus.core.criteria.Order;
import cn.com.rexen.rplus.core.criteria.Restrictions;
import cn.com.rexen.rplus.core.service.IService;
import cn.com.rexen.rplus.core.utils.StringUtils;
import cn.com.rexen.rplus.sa.entity.Operate;
import cn.com.rexen.rplus.sa.entity.Permission;
import cn.com.rexen.rplus.sa.entity.Resource;
import cn.com.rexen.rplus.sa.model.OperateVO;
import cn.com.rexen.rplus.sa.model.ResourceVO;
import cn.com.rexen.rplus.sa.service.OperateService;
import cn.com.rexen.rplus.sa.service.PermissionService;
import cn.com.rexen.rplus.sa.service.ResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * 资源controller.
 *
 * @author zhanghai
 */
@Controller
@RequestMapping(value = ResourceController.REQUEST_PATH)
public class ResourceController extends CURDControllerSupport<Resource, ResourceVO> {

    /**
     * resource模块路径.
     */
    public static final String REQUEST_PATH = "/resource";

    /**
     * 资源对象.
     */
    private Resource resource;

    /**
     * 资源service.
     */
    @Autowired
    private ResourceService resourceService;
    /**
     * 权限service.
     */
    @Autowired
    private PermissionService permissionService;

    /**
     * 操作service.
     */
    @Autowired
    private OperateService operateService;

    /**
     * 操作列表.
     */
    private List<Operate> operateList;

    /*
     * (non-Javadoc)
     * 
     * @see cn.com.rexen.rplus.controller.CURDControllerSupport#getEntity()
     */
    @Override
    public Resource getEntity() {
        if (resource == null) {
            resource = new Resource();
        }
        return resource;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#getEntityService()
     */
    @Override
    protected IService getEntityService() {
        return resourceService;
    }

    @Override
    protected void buildCriteria(Criteria criteria, HttpServletRequest request) {
        String parentId = request.getParameter("parentid");
        if (StringUtils.isNotEmpty(parentId)) {
            criteria.add(Restrictions.eq("parentgroup", parentId));
        }
    }


    /**
     * 将实体对象转换成vo对象.
     *
     * @param resources 实体对象.
     * @return vo 对象列表.
     */
    protected List<ResourceVO> entityConvertVoInList(List<Resource> resources) {
        List<ResourceVO> resourceVOList = new ArrayList<ResourceVO>();
        LOGGER.debug("afterlist@resource ,list:{} ", resources);
        for (Resource _resource : resources) {
            resourceVOList.add(entityConvertVo(_resource));
        }
        return resourceVOList;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#onShow(javax.servlet
     * .http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
     * java.lang.Object, org.springframework.ui.ModelMap)
     */
    @Override
    protected ResourceVO entityConvertVo(Resource resource) {
        if (resource == null) {
            return new ResourceVO();
        }
        String parentId = resource.getParentgroup();
        String parentName = null;
        if (StringUtils.isNotEmpty(parentId)) {
            Resource resourceParent = resourceService.get(Resource.class, parentId);
            if (resourceParent == null) {
                parentName = "";
            } else {
                parentName = StringUtils.isNotEmpty(resourceParent.getName()) ? resourceParent.getName() : "";
            }
        }
        ResourceVO resourceVO = new ResourceVO(resource.getId(), resource.getName(), parentName, parentId);
        resourceVO.setPath(resource.getPath());
        List<Permission> permissions = permissionService.getPermissionByResourceId(resource.getId());
        Criteria criteria = operateService.getCriteria(Operate.class);
        criteria.addOrder(Order.asc("id"));
        List<Operate> operateList = operateService.find(criteria);
        List<OperateVO> op = resourceVO.getOp();
        for (Operate operate : operateList) {
            OperateVO ov = new OperateVO(operate.getId(), false, operate.getName());
            for (Permission permission : permissions) {
                if (permission.getOperate().getId().equals(operate.getId())) {
                    ov.setEnabled(true);
                }
            }
            op.add(ov);
        }
        resourceVO.setOp(op);
        return resourceVO;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#beforeSave(javax.
     * servlet .http.HttpServletRequest, java.lang.Object,
     * org.springframework.validation.BindException,
     * org.springframework.ui.ModelMap)
     */
    @Override
    protected void beforeSave(HttpServletRequest request, HttpServletResponse response, ResourceVO entity,
                              BindException errors, ModelMap mm) {
        resource = new Resource();
        resource.setId(resourceService.generateId());
        resource.setApp(getApps());
        resource.setName(entity.getName());
        resource.setPath(entity.getPath());
        if (StringUtils.isEmpty(entity.getParentgroup())) {
            resource.setParentgroup(ROOT);
        } else {
            resource.setParentgroup(entity.getParentgroup());
        }
        List<OperateVO> op = entity.getOp();
        if (op != null && op.size() > 0) {
            for (OperateVO operateVO : op) {
                if (operateVO.isEnabled()) {
                    Operate operate = operateService.get(Operate.class, operateVO.getId());
                    operate.setEnabled(operateVO.isEnabled());
                    Permission permission = new Permission(permissionService.generateId(), operate, resource);
                    resource.addPermissions(permission);
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#beforeUpdate(javax
     * .servlet.http.HttpServletRequest, java.lang.Object,
     * org.springframework.validation.BindException,
     * org.springframework.ui.ModelMap, java.lang.String)
     */

    @Override
    protected void beforeUpdate(HttpServletRequest request, HttpServletResponse response, ResourceVO entity,
                                BindException errors, ModelMap mm, String id) {
        if (id.equals(entity.getParentgroup())) {
            throw new RuntimeException("父节点与本节点重复.");
        }

        resource = new Resource();
        resource.setId(id);
        resource.setApp(getApps());
        resource.setName(entity.getName());
        resource.setParentgroup(StringUtils.isEmpty(entity.getParentgroup()) ? ROOT : entity.getParentgroup());
        resource.setPath(entity.getPath());
//        resourceService.validateUnique(resource);
        Criteria criteria = resourceService.getCriteria(Resource.class);
        Resource resource2 = resourceService.findOnly(criteria.add(Restrictions.eq("path", entity.getPath())));
        if (resource2 != null) {
            if (!resource2.getId().equals(id)) {
                throw new RuntimeException("资源路径重复.");
            }
        }
        List<OperateVO> op = entity.getOp();
        operateList = new ArrayList<Operate>();
        if (op != null && op.size() > 0) {
            for (OperateVO operateVO : op) {
                // if (operateVO.isEnabled()) {
                Operate operate = operateService.get(Operate.class, operateVO.getId());
                operate.setEnabled(operateVO.isEnabled());
                operateList.add(operate);
                // }
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#doUpdate(javax.servlet
     * .http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    public void doUpdate(HttpServletRequest request, HttpServletResponse response) {
        ResourceService service = (ResourceService) getEntityService();
        service.update(resource, operateList);
    }

    /**
     * 通过资源父id获取资源列表.
     *
     * @param parentId 资源父id
     * @return 返回资源列表的json数据.
     */
    @RequestMapping(value = "/{parentId}/children", method = RequestMethod.GET)
    @ResponseBody
    public ModelMap children(@PathVariable String parentId) {
        ModelMap mm = new ModelMap();
        List<Resource> list = resourceService.getResourceListByParentId(parentId);
        List<ResourceVO> resourceVOList = new ArrayList<ResourceVO>();
        LOGGER.debug("afterlist@resource ,list:{} ", list);
        for (Object object : list) {
            Resource resource = (Resource) object;
            String parentgroupid = resource.getParentgroup();

            String parentName = null;
            if (StringUtils.isNotEmpty(parentgroupid) && !"_root".equalsIgnoreCase(parentgroupid)) {
                Resource resourceParent = resourceService.get(Resource.class, parentgroupid);
                if (resourceParent != null) {
                    parentName = resourceParent.getName();
                } else {
                    parentName = "";
                }
            }
            ResourceVO resourceVO = new ResourceVO(resource.getId(), resource.getName(), parentName,
                    resource.getParentgroup());
            List<Resource> isItemList = resourceService.getResourceListByParentId(resource.getId());
            if (isItemList == null || isItemList.size() <= 0) {
                resourceVO.setType("item");
            } else {
                resourceVO.setType("folder");
            }

            List<Permission> permissions = permissionService.getPermissionByResourceId(resource.getId());
            List<Operate> operateList = operateService.find(operateService.getCriteria(Operate.class));
            List<OperateVO> op = resourceVO.getOp();
            for (Operate operate : operateList) {
                OperateVO ov = new OperateVO(operate.getId(), false, operate.getName());
                for (Permission permission : permissions) {
                    if (permission.getOperate().getId().equals(operate.getId())) {
                        ov.setEnabled(true);
                    }
                }
                op.add(ov);
            }
            resourceVOList.add(resourceVO);
        }
        mm.addAttribute("data", resourceVOList);
        return mm;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * cn.com.rexen.rplus.controller.CURDControllerSupport#doDelete(java.lang
     * .Object)
     */
    @Override
    public void doDelete(Object object) throws Exception {
        Resource resource = (Resource) object;
        //        if (ROOT.equals(resource.getId())) {
        //            throw new RuntimeException("根结点不允许删除.");
        //        }
        List<Resource> isItemList = resourceService.getResourceListByParentId(resource.getId());
        if (isItemList != null && isItemList.size() > 0) {
            throw new RuntimeException("有子结点不允许删除.");
        }
        resourceService.delete(resource);
    }

}
